"""
Case Type   : 故障&可靠性测试
Case Name   : 备机异常，不影响新备机扩容，且异常备机可恢复
Create At   : 2022/4/8
Owner       : n@ningyali
Description :
    1、构造备机1异常场景，比如备库shutdown
    2、备机2扩容
    3、恢复备机1故障
    4、减容备机2
    5、备机2扩容
Expect      :
    1、故障注入成功
    2、备机2扩容成功
    3、故障恢复成功
    4、备机2减容成功
    5、备机2扩容成功
History     :
"""
import os
import re
import time
import unittest
from datetime import datetime

from yat.test import macro

from testcase.utils.ComThread import ComThread
from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH, RestartDbCluster
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger


class GsExpansion21(unittest.TestCase):
    nodes_tuple = ('PrimaryDbUser', 'Standby1DbUser', 'Standby2DbUser')

    @RestartDbCluster(*nodes_tuple)
    def setUp(self):
        self.sh = {'pri_root': CommonSH('PrimaryRoot'),
                   'pri_user': CommonSH(self.nodes_tuple[0]),
                   'sta1_root': CommonSH('Standby1Root'),
                   'sta1_user': CommonSH(self.nodes_tuple[1]),
                   'sta2_user': CommonSH(self.nodes_tuple[2])}
        self.node_num = self.sh['pri_user'].get_node_num()
        self.log = Logger()
        self.cons = Constant()
        self.com = Common()
        text = f'-----{os.path.basename(__file__)} start-----'
        self.log.info(text)

        text = '----预置步骤: 一主两备减容一备，后续用例才能扩容 expect: 成功----'
        self.log.info(text)
        expect_msg = 'Success to drop the target nodes'
        shell_cmd = f'''source {macro.DB_ENV_PATH};
                    expect <<EOF
                    set timeout 300
                    spawn gs_dropnode -U {self.sh['pri_user'].node.ssh_user} \
                    -G {self.sh['pri_user'].node.ssh_user} \
                    -h {self.sh.get("sta2_user").node.ssh_host}
                    expect "*(yes/no)?"
                    send "yes\\n"
                    expect eof''' + "\nEOF\n"
        self.log.info(shell_cmd)
        res = self.com.get_sh_result(self.sh['pri_user'].node, shell_cmd)
        self.assertIn(expect_msg, res, f'执行失败: {text}')

        text = '---预置步骤: 数据库主机解压安装包，以免找不到扩容脚本 expect: 成功---'
        self.log.info(text)
        cmd = f'cd {os.path.dirname(macro.DB_SCRIPT_PATH)} && ' \
            f'tar -xf openGauss-Package-bak*.tar.gz && ' \
            f'ls {macro.DB_SCRIPT_PATH}|grep gs_sshexkey'
        self.log.info(cmd)
        res = self.com.get_sh_result(self.sh.get("pri_root").node, cmd)
        self.assertEqual(res, 'gs_sshexkey', f'执行失败: {text}')

        text = '----预置步骤: 建立root互信 expect: 成功----'
        self.log.info(text)
        ssh_cmd = f'cd {macro.DB_SCRIPT_PATH};' \
            f'echo "{self.sh.get("pri_root").node.ssh_host}\n' \
            f'{self.sh.get("sta1_user").node.ssh_host}\n' \
            f'{self.sh.get("sta2_user").node.ssh_host}" > hosts\n'
        ssh_cmd += f'''expect <<EOF
                            set timeout 300
                            spawn ./gs_sshexkey -f hosts
                            expect "*assword:"
                            send "{self.sh.get(
            "pri_root").node.ssh_password}\\n"
                            expect eof''' + "\nEOF\n"
        ssh_cmd += "source ~/.bashrc"
        self.log.info(ssh_cmd)
        res = self.com.get_sh_result(self.sh.get("pri_root").node, ssh_cmd)
        self.assertIn('Successfully created SSH trust', res, f'执行失败: {text}')

    def test_1(self):
        text = '----step1: 构造备机1异常场景，比如备库shutdown expect: 故障注入成功----'
        self.log.info(text)
        sql_cmd = 'shutdown;'
        res = self.sh['sta1_user'].executDbSql(sql_cmd)
        self.log.info(res)

        time.sleep(10)

        text = '----step2: 备机2扩容 expect: 扩容成功----'
        self.log.info(text)
        expansion_cmd = f'cd {macro.DB_SCRIPT_PATH};' \
            f'source {macro.DB_ENV_PATH}\n' \
            f'./gs_expansion -U {self.sh.get("pri_user").node.ssh_user} ' \
            f'-G {self.sh.get("pri_user").node.ssh_user} ' \
            f'-X {macro.DB_XML_PATH} ' \
            f'-h {self.sh.get("sta2_user").node.ssh_host} -L'
        self.log.info(expansion_cmd)
        res = self.com.get_sh_result(self.sh.get("pri_root").node,
                                     expansion_cmd)
        expect = 'Expansion results:.*:.*Success.*Expansion Finish.'
        regex_res = re.search(expect, res, re.S)
        self.assertIsNotNone(regex_res, f'执行失败: {text}')

        text = '----step3: 恢复备机1故障 expect: 故障恢复成功----'
        self.log.info(text)
        res = self.sh['sta1_user'].executeGsctl('build',
                                                self.cons.BUILD_SUCCESS_MSG,
                                                '-b full',
                                                get_detail=True)
        self.assertTrue(res, f'执行失败: {text}')

        text = '----step4: 备机2减容 expect: 减容成功----'
        self.log.info(text)
        expect_msg = 'Success to drop the target nodes'
        shell_cmd = f'''source {macro.DB_ENV_PATH};
                            expect <<EOF
                            set timeout 300
                            spawn gs_dropnode -U {self.sh[
            'pri_user'].node.ssh_user} \
                            -G {self.sh['pri_user'].node.ssh_user} \
                            -h {self.sh.get("sta2_user").node.ssh_host}
                            expect "*(yes/no)?"
                            send "yes\\n"
                            expect eof''' + "\nEOF\n"
        self.log.info(shell_cmd)
        res = self.com.get_sh_result(self.sh['pri_user'].node, shell_cmd)
        self.assertIn(expect_msg, res, f'执行失败: {text}')

        text = '----step5: 备机2扩容 expect: 备机扩容成功----'
        self.log.info(text)
        expansion_cmd = f'cd {macro.DB_SCRIPT_PATH};' \
            f'source {macro.DB_ENV_PATH}\n' \
            f'./gs_expansion -U {self.sh.get("pri_user").node.ssh_user} ' \
            f'-G {self.sh.get("pri_user").node.ssh_user} ' \
            f'-X {macro.DB_XML_PATH} ' \
            f'-h {self.sh.get("sta2_user").node.ssh_host} -L'
        self.log.info(expansion_cmd)
        res = self.com.get_sh_result(self.sh.get("pri_root").node,
                                     expansion_cmd)
        expect = 'Expansion results:.*:.*Success.*Expansion Finish.'
        regex_res = re.search(expect, res, re.S)
        self.assertIsNotNone(regex_res, f'执行失败: {text}')

    def tearDown(self):
        text = '----run teardown----'
        self.log.info(text)

        text = '----检查集群状态是否正常----'
        self.log.info(text)
        res2 = self.sh['pri_user'].getDbClusterStatus('detail')
        self.log.info(res2)
        self.assertEqual(res2.count('Normal'), self.node_num + 1,
                         f'执行失败: {text}')

        text = f'-----{os.path.basename(__file__)} end-----'
        self.log.info(text)
